/*
 * Hyuga: A Density-Grid Stream Clustering Platform.
 * Copyright (C) 2014 PUC-Rio/Laboratory for Advanced Collaboration
 *
 * Hyuga is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Hyuga is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Hyuga.  If not, see <http://www.gnu.org/licenses/>.
 */
package br.pucrio.inf.lac.konoha.hyuga.others.csv;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.RandomAccessFile;
import java.math.BigDecimal;
import java.math.MathContext;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import java.util.ArrayDeque;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Queue;

import org.apache.log4j.ConsoleAppender;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.apache.log4j.PatternLayout;

import br.pucrio.inf.lac.konoha.hyuga.common.DBSCAN;
import br.pucrio.inf.lac.konoha.hyuga.common.Geo;
import br.pucrio.inf.lac.konoha.hyuga.common.Pair;
import br.pucrio.inf.lac.konoha.hyuga.events.LocationUpdateEvent;
import br.pucrio.inf.lac.konoha.hyuga.events.csv.CSVClusterEvent;
import br.pucrio.inf.lac.konoha.hyuga.events.csv.CSVLocationUpdateEvent;

/**
 * A DBSCAN CSV interpolation log utility. The csv file must have the following columns:
 * id,latitude,longitude,timestamp
 * 
 * Sample File:
 * id,    latitude,          longitude,        timestamp
 * 286,  -22.9559986550780, -43.1922377359216, 70462
 * 973,  -22.9603834270102, -43.2000845051359, 70462
 * 2742, -22.9728237658448, -43.1907249148011, 704637
 * 4075, -22.9788327380116, -43.1908675079309, 70464
 * 878,  -22.9811741072085, -43.2333375518404, 70464
 * 3431, -22.9703160507337, -43.1907072643957, 704650
 * 341,  -22.9656428061742, -43.2163599814267, 70466
 * 5028, -22.9580526401979, -43.2050608584764, 704664
 *
 * @author Marcos Roriz <mroriz@inf.puc-rio.br>
 */
public class CSVLogInterpolation {

    /** LOGGER. */
	private static Logger LOGGER = Logger.getLogger("br.pucrio.inf.lac.konoha.hyuga");
	
	/* DBSCAN. */
	private double eps;
	private int    minPts;
	
	/** Dataset Entries. */
	Map<String,Queue<CSVLocationUpdateEvent>> datasetEntries;
	
	// Start / End Period
	private double startPeriod;
	private double endPeriod;
	
	// Input File
	private File inputFile;
	
	// Output File
	private String outName;
	
	public CSVLogInterpolation(String inName, double eps, int minPts, double time, double period, String outName) throws FileNotFoundException {
	    // DBSCAN variables
	    this.eps    = eps;
	    this.minPts = minPts;
	    
	    // Dataset Entries
	    this.datasetEntries = new HashMap<>();
	    
	    // CSV variables
	    this.startPeriod  = time - period;
	    this.endPeriod    = time;
        this.inputFile    = new File(inName);
        this.outName      = outName;
        
        if (startPeriod < 0) startPeriod = 0;
        
        if (!inputFile.exists()) {
            throw new FileNotFoundException();
        }
    }
	
	public void parse() throws IOException {
        // Local variables (reused)
        String line   = "";
        double minlat = -23.069387;
        double maxlat = -22.766447;
        double minlng = -43.784981;
        double maxlng = -43.142967;

        // Log Input
	    FileReader fr = new FileReader(inputFile);
	    BufferedReader buffer = new BufferedReader(fr);
	    buffer.readLine(); // header
        
	    while ((line = buffer.readLine()) != null) {
	        if (Integer.parseInt(line.split(",")[3]) >= startPeriod) {
	            String[] data = line.split(",");
	            
	            String   id        = data[0];
                double   latitude  = Double.parseDouble(data[1]);
	            double   longitude = Double.parseDouble(data[2]);
	            long     timestamp = Long.parseLong(data[3]);
	            
	            if (minlng <= longitude && longitude <= maxlng && 
	                minlat <= latitude  && latitude <= maxlat  && timestamp <= endPeriod) {
	                
	                if (!datasetEntries.containsKey(id)) { 
	                    datasetEntries.put(id, new ArrayDeque<CSVLocationUpdateEvent>());
	                }
	                datasetEntries.get(id).add(new CSVLocationUpdateEvent(id, latitude, longitude, timestamp));
	            }
	        }
	    }
	    
	    // Log Output
        File traceFile = new File(outName + "log.csv");
        if (!traceFile.exists()) {
            traceFile.createNewFile();
        }
        
        PrintWriter traceFileWriter = new PrintWriter(new BufferedWriter(new FileWriter(traceFile, true)));
        traceFileWriter.println("uuid,latitude,longitude,timestamp");

        // Interpolate every datapoint
        for (String id : datasetEntries.keySet()) {
            Queue<CSVLocationUpdateEvent> entryQueue = datasetEntries.get(id);
            
            CSVLocationUpdateEvent previousEntry = null;
            for (CSVLocationUpdateEvent currentEntry : entryQueue) {
                if (previousEntry == null) {
//                    traceFileWriter.println(currentEntry.toCSVLog());
                } else if (isNearLastStop(currentEntry,50)) {
                    System.out.println("merda");
                    System.out.println(previousEntry.getLatitude() + "," + previousEntry.getLongitude());
                    System.out.println(currentEntry.getLatitude() + "," + currentEntry.getLongitude());
                } else if (isNearLastStop(currentEntry,100) && previousEntry != null && 
                           Geo.distanceFrom(previousEntry.toLU(), currentEntry.toLU()) <= 15) {
                    System.out.println("before");
                    System.out.println(previousEntry.getLatitude() + "," + previousEntry.getLongitude());
                    System.out.println(currentEntry.getLatitude() + "," + currentEntry.getLongitude());
                } else { //if (Geo.distanceFrom(previousEntry.toLU(), currentEntry.toLU()) >= 10) {
                        System.out.println("before");
                        System.out.println(previousEntry.getLatitude() + "," + previousEntry.getLongitude());
                        System.out.println(currentEntry.getLatitude() + "," + currentEntry.getLongitude());
                    
                    Queue<CSVLocationUpdateEvent> interpolateEntries = interpolate(previousEntry, currentEntry);
                    for (CSVLocationUpdateEvent inEntry : interpolateEntries) {
                        traceFileWriter.println(inEntry.toCSVLog());
                    }
                    traceFileWriter.flush();
                }
                
                previousEntry = currentEntry;
            }
        }
        
	    traceFileWriter.flush();
	    traceFileWriter.close();
	    buffer.close();
	}

    
    private boolean isNearLastStop(CSVLocationUpdateEvent currentEntry, int threshold) {
        boolean near = false;
        
        for (LocationUpdateEvent lastStop : pointsToAvoid) {
            if (Geo.distanceFrom(lastStop, currentEntry.toLU()) <= threshold) {
                near = true;
                break;
            }
        }
        
        return near;
    }

    private Queue<CSVLocationUpdateEvent> interpolate(CSVLocationUpdateEvent previousEntry, CSVLocationUpdateEvent currentEntry) {
        ArrayDeque<CSVLocationUpdateEvent> queue = new ArrayDeque<>();
        
        double period = currentEntry.getTimestamp() - previousEntry.getTimestamp();
        period = period / 1000;

        double vlat = currentEntry.getLatitude()  - previousEntry.getLatitude();
        double vlng = currentEntry.getLongitude() - previousEntry.getLongitude();
        vlat = vlat / period;
        vlng = vlng / period;
            
        // System.out.println(previousEntry.getLatitude() + "," + previousEntry.getLongitude());
        // System.out.println(currentEntry.getLatitude()  + "," + currentEntry.getLongitude());
        // System.out.println((previousEntry.getLatitude() + vlat*period) + "," + (previousEntry.getLongitude() + vlng*period));
        for (int i = 1; i <= period; i++) {
            System.out.println((previousEntry.getLatitude() + vlat*i) + "," + (previousEntry.getLongitude() + vlng*i));
            queue.add(new CSVLocationUpdateEvent(previousEntry.getUuid(),
                                                 previousEntry.getLatitude()  + vlat*i,
                                                 previousEntry.getLongitude() + vlng*i,
                                                 previousEntry.getTimestamp() + (i*1000)));
        }
        return queue;
    }

    public Pair<Double,Double> clusterCentroid (List<CSVLocationUpdateEvent> points) {
        double lat = 0;
        double lng = 0;
        
        for (CSVLocationUpdateEvent point : points) {
            lat += point.getLatitude();
            lng += point.getLongitude();
        }
    
       return new Pair<Double, Double>(lat/points.size(), lng/points.size());
    }

    
	/**
	 * Main Routine.
	 * 
	 * @param args a CSV filename.
	 * @throws IOException If log files cannot be created.
	 * @throws IllegalAccessException if args is null. 
	 */
	public static void main(String[] args) throws IOException {
	    // Validate args
	    if (args.length != 6) {
	        System.out.println("Usage:  java -jar CSVLog.jar csv.file     eps  minPts  time (in ms)  backwindow (in ms)  output.file");
	        System.out.println("Sample: java -jar CSVLog.jar dataset.csv  800  40      39600000      300000              out.csv");
	        System.exit(-1);
	    }
	    
		// Logging
		ConsoleAppender	consoleAppender = new ConsoleAppender(new PatternLayout("[%-4p] [%c] %m%n"));
		
		Logger.getRootLogger().setLevel(Level.INFO);
		Logger.getLogger("br.pucrio.inf.lac").addAppender(consoleAppender);
        Logger.getLogger("br.pucrio.inf.lac").setLevel(Level.INFO);

        String cmdLine = "";
        for (String arg : args) { 
            cmdLine += arg + " ";
        }
        LOGGER.info("CMD LINE: java -jar " + cmdLine);
        
        // CSV
        CSVLogInterpolation csv = new CSVLogInterpolation(args[0],                     // Input File (csv)
                                      Double.parseDouble(args[1]), // Eps
                                      Integer.parseInt(args[2]),   // minPts
                                      Double.parseDouble(args[3]), // Time
                                      Double.parseDouble(args[4]), // Time Window
                                      args[5]);                    // Output File (csv)
		csv.parse();
	}

	
	// Last Stops
	private LocationUpdateEvent[] pointsToAvoid = {
	        new LocationUpdateEvent(-22.929581, -43.253885), // Auto Aviação Tijuca
	        new LocationUpdateEvent(-22.929456, -43.254133), // Auto Aviação Tijuca
	        new LocationUpdateEvent(-22.929340, -43.253663), // Auto Aviação Tijuca
	        new LocationUpdateEvent(-22.929854, -43.253789), // Auto Aviação Tijuca
	        new LocationUpdateEvent(-22.952778, -43.348923), // Viação Redentor
	        new LocationUpdateEvent(-22.951224, -43.347676), // Viação Redentor
	        new LocationUpdateEvent(-22.951827, -43.348282), // Viação Redentor
	        new LocationUpdateEvent(-22.952118, -43.349296), // Viação Redentor
	        new LocationUpdateEvent(-22.951425, -43.348866), // Viação Redentor
	        new LocationUpdateEvent(-22.951766, -43.349574), // Viação Redentor
	        new LocationUpdateEvent(-22.951265, -43.348603), // Viação Redentor
	        new LocationUpdateEvent(-22.804225, -43.310295), // Viação VG
	        new LocationUpdateEvent(-22.804410, -43.309762), // Viação VG
	        new LocationUpdateEvent(-22.804635, -43.309877), // Viação VG
	        new LocationUpdateEvent(-22.804806, -43.309477), // Viação VG
	        new LocationUpdateEvent(-22.804182, -43.309514), // Viação VG
	        new LocationUpdateEvent(-22.804834, -43.309422), // Viação VG
	        new LocationUpdateEvent(-22.919665, -43.643964), // Viação Algarve
	        new LocationUpdateEvent(-22.919977, -43.644382), // Viação Algarve
	        new LocationUpdateEvent(-22.919275, -43.644141), // Viação Algarve
	        new LocationUpdateEvent(-22.920120, -43.644929), // Viação Algarve
	        new LocationUpdateEvent(-22.939944, -43.199883), // Rodoviária Cosme Velho
	        new LocationUpdateEvent(-22.940041, -43.199588), // Rodoviária Cosme Velho
	        new LocationUpdateEvent(-22.901564, -43.208064), // Terminal Padre Henrique Otte
	        new LocationUpdateEvent(-22.901813, -43.555431), // Terminal BRT Campo Grande
	        new LocationUpdateEvent(-22.901596, -43.554583), // Terminal BRT Campo Grande
	        new LocationUpdateEvent(-22.901927, -43.554454), // Terminal BRT Campo Grande
	        new LocationUpdateEvent(-22.902100, -43.555919), // Terminal BRT Campo Grande
	        new LocationUpdateEvent(-22.905311, -43.170797), // Terminal da Misericordia
	        new LocationUpdateEvent(-22.905079, -43.171391), // Terminal da Misericordia
	        new LocationUpdateEvent(-22.905430, -43.170522), // Terminal da Misericordia
	        new LocationUpdateEvent(-22.905543, -43.171112), // Terminal da Misericordia
	        new LocationUpdateEvent(-22.917575, -43.608226), // Expresso Pégasos
	        new LocationUpdateEvent(-22.916378, -43.608250), // Expresso Pégasos
	        new LocationUpdateEvent(-22.917000, -43.608218), // Expresso Pégasos
	        new LocationUpdateEvent(-22.917188, -43.608744), // Expresso Pégasos
	        new LocationUpdateEvent(-22.916901, -43.607971), // Expresso Pégasos
	        new LocationUpdateEvent(-23.001333, -43.366073), // Terminal Alvorada
	        new LocationUpdateEvent(-23.001393, -43.367862), // Terminal Alvorada
	        new LocationUpdateEvent(-23.000558, -43.368082), // Terminal Alvorada
	        new LocationUpdateEvent(-23.000697, -43.364601), // Terminal Alvorada
            new LocationUpdateEvent(-23.001368, -43.364671), // Terminal Alvorada
            new LocationUpdateEvent(-23.001037, -43.368206), // Terminal Alvorada
            new LocationUpdateEvent(-23.001003, -43.364038), // Terminal Alvorada
            new LocationUpdateEvent(-23.001327, -43.365714), // Terminal Alvorada
            new LocationUpdateEvent(-23.001070, -43.366529), // Terminal Alvorada
            new LocationUpdateEvent(-23.001040, -43.366626), // Terminal Alvorada
	        new LocationUpdateEvent(-22.979279, -43.231553), // PUC
	        new LocationUpdateEvent(-22.979239, -43.230796), // PUC
	        new LocationUpdateEvent(-22.908929, -43.177076), // Terminal America Fontelle
	        new LocationUpdateEvent(-22.946376, -43.256629), // Terminal da Usina
	        new LocationUpdateEvent(-22.905087, -43.192573), // Terminal Procócio Ferreira
	        new LocationUpdateEvent(-22.904753, -43.191936), // Terminal Procócio Ferreira
	        new LocationUpdateEvent(-22.905059, -43.192956), // Terminal Procócio Ferreira
            new LocationUpdateEvent(-22.905212, -43.192349), // Terminal Procócio Ferreira
            new LocationUpdateEvent(-22.905361, -43.192966), // Terminal Procócio Ferreira
            new LocationUpdateEvent(-22.904921, -43.191641), // Terminal Procócio Ferreira
            new LocationUpdateEvent(-22.901491, -43.195804), // Terminal Procócio Ferreira
	        new LocationUpdateEvent(-22.901838, -43.555106), // Terminal Campo Grande
	        new LocationUpdateEvent(-22.883931, -43.495275), // Transportes Campo Grande
	        new LocationUpdateEvent(-22.901838, -43.555106), // Terminal Campo Grande
	        new LocationUpdateEvent(-22.810269, -43.342977), // Transporte América
	        new LocationUpdateEvent(-22.809804, -43.342210), // Transporte América
	        new LocationUpdateEvent(-22.809695, -43.343792), // Transporte América
	        new LocationUpdateEvent(-22.810357, -43.341955), // Transporte América
	        new LocationUpdateEvent(-22.815070, -43.187656), // Transporte Paranapauan
	        new LocationUpdateEvent(-22.814985, -43.187432), // Transporte Paranapauan
	        new LocationUpdateEvent(-22.814619, -43.187775), // Transporte Paranapauan
	        new LocationUpdateEvent(-22.815338, -43.187359), // Transporte Paranapauan
	        new LocationUpdateEvent(-22.876458, -43.329993), // Viação Acari
	        new LocationUpdateEvent(-22.876818, -43.329992), // Viação Acari
	        new LocationUpdateEvent(-22.876368, -43.330419), // Viação Acari
	        new LocationUpdateEvent(-22.836994, -43.284920), // Viação Nossa Senhora de Lourdes
	        new LocationUpdateEvent(-22.837519, -43.285704), // Viação Nossa Senhora de Lourdes
	        new LocationUpdateEvent(-22.836703, -43.285371), // Viação Nossa Senhora de Lourdes
	        new LocationUpdateEvent(-22.836886, -43.286272), // Viação Nossa Senhora de Lourdes
	        new LocationUpdateEvent(-22.953062, -43.350406), // Viação Redentor
	        new LocationUpdateEvent(-22.952885, -43.349975), // Viação Redentor
	        new LocationUpdateEvent(-22.953171, -43.348988), // Viação Redentor
	        new LocationUpdateEvent(-22.952806, -43.350844), // Viação Redentor
	        new LocationUpdateEvent(-22.952618, -43.350828), // Viação Redentor
	        new LocationUpdateEvent(-22.880084, -43.357366), // Transportes Barra
	        new LocationUpdateEvent(-22.879362, -43.357367), // Transportes Barra
	        new LocationUpdateEvent(-22.880029, -43.357056), // Transportes Barra
	        new LocationUpdateEvent(-22.880123, -43.358102), // Transportes Barra
	        new LocationUpdateEvent(-22.880415, -43.356965), // Transportes Barra
	        new LocationUpdateEvent(-22.879515, -43.356954), // Transportes Barra
	        new LocationUpdateEvent(-22.880336, -43.356965), // Transportes Barra
	        new LocationUpdateEvent(-22.880553, -43.356637), // Transportes Barra
	        new LocationUpdateEvent(-22.880084, -43.357366), // Transportes Barra
	        new LocationUpdateEvent(-22.945566, -43.344052), // Shop Jacarepaguá
	        new LocationUpdateEvent(-22.945406, -43.344026), // Shop Jacarepaguá
	        new LocationUpdateEvent(-22.944862, -43.344246), // Shop Jacarepaguá
	        new LocationUpdateEvent(-22.945228, -43.343870), // Shop Jacarepaguá
	        new LocationUpdateEvent(-22.944813, -43.344766), // Shop Jacarepaguá
	        new LocationUpdateEvent(-22.945154, -43.343897), // Shop Jacarepaguá
	        new LocationUpdateEvent(-22.944309, -43.344594), // Shop Jacarepaguá
	        new LocationUpdateEvent(-22.945766, -43.345608), // Shop Jacarepaguá
	        new LocationUpdateEvent(-22.944867, -43.345683), // Shop Jacarepaguá
	        new LocationUpdateEvent(-22.811871, -43.372652), // Estação Pavuna
	        new LocationUpdateEvent(-22.811625, -43.372822), // Estação Pavuna
	        new LocationUpdateEvent(-22.811560, -43.373610), // Estação Pavuna
	        new LocationUpdateEvent(-22.811941, -43.373578), // Estação Pavuna
	        new LocationUpdateEvent(-22.812124, -43.373305), // Estação Pavuna
	        new LocationUpdateEvent(-22.811120, -43.372355), // Estação Pavuna
	        new LocationUpdateEvent(-22.811175, -43.372677), // Estação Pavuna
	        new LocationUpdateEvent(-22.811476, -43.372221), // Estação Pavuna
	        new LocationUpdateEvent(-22.811066, -43.373149), // Estação Pavuna
	        new LocationUpdateEvent(-22.811135, -43.373417), // Estação Pavuna
	        new LocationUpdateEvent(-22.811274, -43.372436), // Estação Pavuna
	        new LocationUpdateEvent(-22.859464, -43.371012), // Transportes Estrela
	        new LocationUpdateEvent(-22.858653, -43.371212), // Transportes Estrela
	        new LocationUpdateEvent(-22.858841, -43.370896), // Transportes Estrela
	        new LocationUpdateEvent(-22.858149, -43.371127), // Transportes Estrela
	        new LocationUpdateEvent(-22.857452, -43.371320), // Transportes Estrela
	        new LocationUpdateEvent(-22.856374, -43.371658), // Transportes Estrela
	        new LocationUpdateEvent(-22.855583, -43.371438), // Transportes Estrela
	        new LocationUpdateEvent(-22.857021, -43.371540), // Transportes Estrela
	        new LocationUpdateEvent(-22.859305, -43.370912), // Transportes Estrela
	        new LocationUpdateEvent(-22.859765, -43.370687), // Transportes Estrela
	        new LocationUpdateEvent(-22.859730, -43.371341), // Transportes Estrela
	        new LocationUpdateEvent(-22.815308, -43.386385), // Outro Ponto Final Pavuna
	        new LocationUpdateEvent(-22.815309, -43.386914), // Outro Ponto Final Pavuna
	        new LocationUpdateEvent(-22.815453, -43.386807), // Outro Ponto Final Pavuna
	        new LocationUpdateEvent(-22.814973, -43.386093), // Outro Ponto Final Pavuna
	        new LocationUpdateEvent(-22.814563, -43.386152), // Outro Ponto Final Pavuna
	        new LocationUpdateEvent(-22.814820, -43.386855), // Outro Ponto Final Pavuna
	        new LocationUpdateEvent(-22.815156, -43.386962), // Outro Ponto Final Pavuna
	        new LocationUpdateEvent(-22.815557, -43.386056), // Outro Ponto Final Pavuna
	        new LocationUpdateEvent(-22.815730, -43.386667), // Outro Ponto Final Pavuna
	        new LocationUpdateEvent(-22.815754, -43.386040), // Outro Ponto Final Pavuna
	        new LocationUpdateEvent(-22.868162, -43.257273), // Ponto Final Bonsucesso
	        new LocationUpdateEvent(-22.868524, -43.257224), // Ponto Final Bonsucesso
	        new LocationUpdateEvent(-22.868642, -43.257208), // Ponto Final Bonsucesso
	        new LocationUpdateEvent(-22.867985, -43.257251), // Ponto Final Bonsucesso
	        new LocationUpdateEvent(-22.868272, -43.256907), // Ponto Final Bonsucesso
	        new LocationUpdateEvent(-22.868262, -43.257589), // Ponto Final Bonsucesso
	        new LocationUpdateEvent(-22.868529, -43.257546), // Ponto Final Bonsucesso
	        new LocationUpdateEvent(-22.867847, -43.257374), // Ponto Final Bonsucesso
	        new LocationUpdateEvent(-22.867916, -43.257058), // Ponto Final Bonsucesso
	        new LocationUpdateEvent(-22.876902, -43.368353), // Novacap
	        new LocationUpdateEvent(-22.876257, -43.368533), // Novacap
	        new LocationUpdateEvent(-22.876281, -43.368096), // Novacap
	        new LocationUpdateEvent(-22.876351, -43.368922), // Novacap
	        new LocationUpdateEvent(-22.876773, -43.368906), // Novacap
	        new LocationUpdateEvent(-22.876845, -43.368082), // Novacap
	        new LocationUpdateEvent(-22.876536, -43.368493), // Novacap
	        new LocationUpdateEvent(-22.877860, -43.368171), // Novacap
	        new LocationUpdateEvent(-22.877663, -43.368718), // Novacap
	        new LocationUpdateEvent(-22.877880, -43.368852), // Novacap
	        new LocationUpdateEvent(-22.877401, -43.368705), // Novacap
	        new LocationUpdateEvent(-22.877433, -43.367967), // Novacap
	        new LocationUpdateEvent(-22.877633, -43.367777), // Novacap
	        new LocationUpdateEvent(-22.877863, -43.367417), // Novacap
	        new LocationUpdateEvent(-22.877999, -43.367659), // Novacap
	        new LocationUpdateEvent(-22.877890, -43.368096), // Novacap
	        new LocationUpdateEvent(-22.877564, -43.368520), // Novacap
	        new LocationUpdateEvent(-22.877915, -43.368619), // Novacap
	        new LocationUpdateEvent(-22.877391, -43.368680), // Novacap
	        new LocationUpdateEvent(-22.877393, -43.368171), // Novacap
	        new LocationUpdateEvent(-22.831097, -43.323649), // Viação Madureira Candelária
	        new LocationUpdateEvent(-22.831468, -43.323147), // Viação Madureira Candelária
	        new LocationUpdateEvent(-22.831557, -43.323727), // Viação Madureira Candelária
	        new LocationUpdateEvent(-22.830899, -43.323979), // Viação Madureira Candelária
	        new LocationUpdateEvent(-22.831225, -43.324161), // Viação Madureira Candelária
	        new LocationUpdateEvent(-22.830978, -43.323442), // Viação Madureira Candelária
	        new LocationUpdateEvent(-22.831389, -43.323126), // Viação Madureira Candelária
	        new LocationUpdateEvent(-22.830662, -43.323839), // Viação Madureira Candelária
	        new LocationUpdateEvent(-22.830439, -43.324419), // Viação Madureira Candelária
	        new LocationUpdateEvent(-22.830103, -43.324097), // Viação Madureira Candelária
	        new LocationUpdateEvent(-22.829846, -43.324043), // Viação Madureira Candelária
	        new LocationUpdateEvent(-22.830464, -43.324488), // Viação Madureira Candelária
	        new LocationUpdateEvent(-22.830652, -43.324429), // Viação Madureira Candelária
	        new LocationUpdateEvent(-22.830944, -43.324156), // Viação Madureira Candelária
	        new LocationUpdateEvent(-22.831542, -43.323984), // Viação Madureira Candelária
	        new LocationUpdateEvent(-22.831132, -43.323829), // Viação Madureira Candelária
	        new LocationUpdateEvent(-22.876314, -43.419758), // Garagem Auto Viação Bangu
	        new LocationUpdateEvent(-22.876916, -43.420136), // Garagem Auto Viação Bangu
	        new LocationUpdateEvent(-22.876368, -43.420731), // Garagem Auto Viação Bangu
	        new LocationUpdateEvent(-22.876635, -43.420404), // Garagem Auto Viação Bangu
	        new LocationUpdateEvent(-22.875844, -43.420157), // Garagem Auto Viação Bangu
	        new LocationUpdateEvent(-22.876205, -43.419868), // Garagem Auto Viação Bangu
	        new LocationUpdateEvent(-22.876516, -43.419471), // Garagem Auto Viação Bangu
	        new LocationUpdateEvent(-22.875498, -43.419685), // Garagem Auto Viação Bangu
	        new LocationUpdateEvent(-22.875799, -43.419256), // Garagem Auto Viação Bangu
	        new LocationUpdateEvent(-22.876111, -43.418913), // Garagem Auto Viação Bangu
	        new LocationUpdateEvent(-22.875300, -43.419358), // Garagem Auto Viação Bangu
	        new LocationUpdateEvent(-22.875532, -43.419063), // Garagem Auto Viação Bangu
	        new LocationUpdateEvent(-22.875829, -43.418688), // Garagem Auto Viação Bangu
	        new LocationUpdateEvent(-22.902321, -43.298507), // Ponto Final Meier
	        new LocationUpdateEvent(-22.901837, -43.298530), // Ponto Final Meier
	        new LocationUpdateEvent(-22.901898, -43.298184), // Ponto Final Meier
	        new LocationUpdateEvent(-22.902007, -43.298436), // Ponto Final Meier
	        new LocationUpdateEvent(-22.902047, -43.299289), // Ponto Final Meier
	        new LocationUpdateEvent(-22.902264, -43.299410), // Ponto Final Meier
	        new LocationUpdateEvent(-22.902407, -43.298897), // Ponto Final Meier
	        new LocationUpdateEvent(-22.902019, -43.298817), // Ponto Final Meier
	        new LocationUpdateEvent(-22.901698, -43.298981), // Ponto Final Meier
	        new LocationUpdateEvent(-22.902215, -43.298353), // Ponto Final Meier
	        new LocationUpdateEvent(-22.902444, -43.298498), // Ponto Final Meier
	        new LocationUpdateEvent(-22.902514, -43.298830), // Ponto Final Meier
	        new LocationUpdateEvent(-22.902182, -43.298887), // Ponto Final Meier
	        new LocationUpdateEvent(-22.902306, -43.299069), // Ponto Final Meier
	        new LocationUpdateEvent(-22.901918, -43.298270), // Ponto Final Meier
	        new LocationUpdateEvent(-22.902014, -43.298463), // Ponto Final Meier
	        new LocationUpdateEvent(-22.894572, -43.532716), // Auto Viação Jabur
	        new LocationUpdateEvent(-22.893097, -43.532006), // Auto Viação Jabur
	        new LocationUpdateEvent(-22.893354, -43.531780), // Auto Viação Jabur
	        new LocationUpdateEvent(-22.893907, -43.531340), // Auto Viação Jabur
	        new LocationUpdateEvent(-22.894214, -43.531115), // Auto Viação Jabur
	        new LocationUpdateEvent(-22.893532, -43.532424), // Auto Viação Jabur
	        new LocationUpdateEvent(-22.893878, -43.532950), // Auto Viação Jabur
	        new LocationUpdateEvent(-22.894075, -43.532478), // Auto Viação Jabur
	        new LocationUpdateEvent(-22.894401, -43.532199), // Auto Viação Jabur
	        new LocationUpdateEvent(-22.894836, -43.531812), // Auto Viação Jabur
	        new LocationUpdateEvent(-22.895232, -43.532231), // Auto Viação Jabur
	        new LocationUpdateEvent(-22.894856, -43.532681), // Auto Viação Jabur
	        new LocationUpdateEvent(-22.894283, -43.533272), // Auto Viação Jabur
	        new LocationUpdateEvent(-22.894619, -43.533787), // Auto Viação Jabur
	        new LocationUpdateEvent(-22.895153, -43.533518), // Auto Viação Jabur
	        new LocationUpdateEvent(-22.895617, -43.533314), // Auto Viação Jabur
	        new LocationUpdateEvent(-22.896131, -43.533202), // Auto Viação Jabur
	        new LocationUpdateEvent(-22.896798, -43.532982), // Auto Viação Jabur
	        new LocationUpdateEvent(-22.897139, -43.532837), // Auto Viação Jabur
	        new LocationUpdateEvent(-22.896260, -43.532504), // Auto Viação Jabur
	        new LocationUpdateEvent(-22.895543, -43.532499), // Auto Viação Jabur
	        new LocationUpdateEvent(-22.895390, -43.532848), // Auto Viação Jabur
	        new LocationUpdateEvent(-22.894169, -43.533454), // Auto Viação Jabur
	        new LocationUpdateEvent(-22.894580, -43.531780), // Auto Viação Jabur
	        new LocationUpdateEvent(-22.894461, -43.531233), // Auto Viação Jabur
	        new LocationUpdateEvent(-22.950112, -43.348067), // Viação Redentor
	        new LocationUpdateEvent(-22.949670, -43.348253), // Viação Redentor
	        new LocationUpdateEvent(-22.949739, -43.347931), // Viação Redentor
	        new LocationUpdateEvent(-22.949754, -43.347657), // Viação Redentor
	        new LocationUpdateEvent(-22.950080, -43.347529), // Viação Redentor
	        new LocationUpdateEvent(-22.950564, -43.347743), // Viação Redentor
	        new LocationUpdateEvent(-22.950213, -43.348076), // Viação Redentor
	        new LocationUpdateEvent(-22.950070, -43.348365), // Viação Redentor
	        new LocationUpdateEvent(-22.950272, -43.348441), // Viação Redentor
	        new LocationUpdateEvent(-22.950524, -43.348623), // Viação Redentor
	        new LocationUpdateEvent(-22.950919, -43.348816), // Viação Redentor
	        new LocationUpdateEvent(-22.951369, -43.349106), // Viação Redentor
	        new LocationUpdateEvent(-22.951621, -43.348913), // Viação Redentor
	        new LocationUpdateEvent(-22.951868, -43.349985), // Viação Redentor
	        new LocationUpdateEvent(-22.952164, -43.350677), // Viação Redentor
	        new LocationUpdateEvent(-22.952683, -43.351423), // Viação Redentor
	        new LocationUpdateEvent(-22.953113, -43.351321), // Viação Redentor
	        new LocationUpdateEvent(-22.953473, -43.350849), // Viação Redentor
	        new LocationUpdateEvent(-22.953503, -43.349669), // Viação Redentor
	        new LocationUpdateEvent(-22.953300, -43.349985), // Viação Redentor
	        new LocationUpdateEvent(-22.952989, -43.350549), // Viação Redentor
	        new LocationUpdateEvent(-22.952342, -43.350441), // Viação Redentor
	        new LocationUpdateEvent(-22.952713, -43.350007), // Viação Redentor
	        new LocationUpdateEvent(-22.953083, -43.348784), // Viação Redentor
	        new LocationUpdateEvent(-22.952303, -43.349395), // Viação Redentor
	        new LocationUpdateEvent(-22.952396, -43.348821), // Viação Redentor
	        new LocationUpdateEvent(-22.952678, -43.348215), // Viação Redentor
	        new LocationUpdateEvent(-22.951902, -43.347818), // Viação Redentor
	        new LocationUpdateEvent(-22.952910, -43.348489), // Viação Redentor
	        new LocationUpdateEvent(-22.952792, -43.350785), // Viação Redentor
	        new LocationUpdateEvent(-22.953044, -43.350066), // Viação Redentor
	        new LocationUpdateEvent(-22.951325, -43.348564), // Viação Redentor
	        new LocationUpdateEvent(-22.951626, -43.347936), // Viação Redentor
	        new LocationUpdateEvent(-22.951162, -43.347695), // Viação Redentor
	        new LocationUpdateEvent(-22.950416, -43.347550), // Viação Redentor
	        new LocationUpdateEvent(-22.950455, -43.348081), // Viação Redentor
	        new LocationUpdateEvent(-22.951018, -43.347770), // Viação Redentor
	        new LocationUpdateEvent(-22.949393, -43.347974), // Viação Redentor
	        new LocationUpdateEvent(-22.950085, -43.348049), // Viação Redentor
	        new LocationUpdateEvent(-22.949329, -43.347539), // Viação Redentor
	        new LocationUpdateEvent(-22.957520, -43.345901), // Litoral Rio Transportes
	        new LocationUpdateEvent(-22.957099, -43.346579), // Litoral Rio Transportes
	        new LocationUpdateEvent(-22.957435, -43.346708), // Litoral Rio Transportes
	        new LocationUpdateEvent(-22.957810, -43.346794), // Litoral Rio Transportes
	        new LocationUpdateEvent(-22.958136, -43.346955), // Litoral Rio Transportes
	        new LocationUpdateEvent(-22.958166, -43.346708), // Litoral Rio Transportes
	        new LocationUpdateEvent(-22.957682, -43.346708), // Litoral Rio Transportes
	        new LocationUpdateEvent(-22.957148, -43.346483), // Litoral Rio Transportes
	        new LocationUpdateEvent(-22.957810, -43.345946), // Litoral Rio Transportes
	        new LocationUpdateEvent(-22.957909, -43.345238), // Litoral Rio Transportes
	        new LocationUpdateEvent(-22.958176, -43.345753), // Litoral Rio Transportes
	        new LocationUpdateEvent(-22.958205, -43.346053), // Litoral Rio Transportes
	        new LocationUpdateEvent(-22.957840, -43.344573), // Litoral Rio Transportes
	        new LocationUpdateEvent(-22.957346, -43.344755), // Litoral Rio Transportes
	        new LocationUpdateEvent(-22.956872, -43.345420), // Litoral Rio Transportes
	        new LocationUpdateEvent(-22.957504, -43.345635), // Litoral Rio Transportes
	        new LocationUpdateEvent(-22.957395, -43.346182), // Litoral Rio Transportes
	        new LocationUpdateEvent(-22.957454, -43.346676), // Litoral Rio Transportes
	        new LocationUpdateEvent(-22.956990, -43.346236), // Litoral Rio Transportes
	        new LocationUpdateEvent(-22.857781, -43.244942), // Unknown
	        new LocationUpdateEvent(-22.857771, -43.244513), // Unknown
	        new LocationUpdateEvent(-22.857692, -43.244792), // Unknown
            new LocationUpdateEvent(-22.857602, -43.244997), // Unknown
            new LocationUpdateEvent(-22.857608, -43.244520), // Unknown
	};
	
}
